﻿using System.Globalization;
using System.Linq;
using Fuse8.DomainFramework.BusinessService;
using Fuse8.DomainFramework.Common.Locator;
using Fuse8.DomainFramework.DataAccess.InMemoryDatabase;
using Fuse8.GlobalizationFramework.BusinessServices;
using Fuse8.GlobalizationFramework.Domain;
using Fuse8.GlobalizationFramework.Domain.Commands;
using Microsoft.Practices.Unity;
using Moq;
using NUnit.Framework;

namespace UnitTests
{
    [TestFixture]
    public class ResourceServiceTests
    {
        private const string ExpectedExistingValue = "my test value";
        private const string ExpectedExistingKey = "common-key";
        private const string ExpectedNotExistingVlaue = "*DEFAULT common-key-not-exists*";
        private const string ExpectedNotExistingKey = "common-key-not-exists";

        [TestFixtureSetUp]
        public void SetUp()
        {
            IUnityContainer container = new UnityContainer();
            var locator = new UnityServiceLocatorWithLazy(container);
            DependencyServiceLocator.SetLocatorProvider(() => locator);

            var entityDataRepository = InMemoryDataRepositoryConfiguration<Resource, int>.CreateRepository();
            entityDataRepository.Add(new Resource()
                                         {
                                             Key = ExpectedExistingKey,
                                             Value = ExpectedExistingValue,
                                             Locale = CultureInfo.CurrentCulture.Name
                                         });
            container.RegisterInstance(entityDataRepository);
            var factory = new Mock<IResourceCommandFactory>();
            factory.Setup(p => p.GetCommand<ResourceByKeyAndLocale>()).Returns(
                new ResourceByKeyAndLocaleInMemoryCommand());
            container.RegisterInstance(factory.Object);
        }

        [Test]        
        public void FindValue_JustKeyExistsInDatabase_ValueFromDatabase()
        {
            string valueFromDatabase = ResourceService.FindValue(ExpectedExistingKey);
            Assert.AreEqual(ExpectedExistingValue, valueFromDatabase);
        }

        [Test]
        public void FindValue_JustKeyNotExistsInDatabase_DefaultFormattedValue()
        {
            string valueFromDatabase = ResourceService.FindValue(ExpectedNotExistingKey);
            Assert.AreEqual(ExpectedNotExistingVlaue, valueFromDatabase);
        }

        [Test]
        public void FindValue_KeyAndNullInDefaultValueExistsInDatabase_ValueFromDatabase()
        {
            string valueFromDatabase = ResourceService.FindValue(ExpectedExistingKey, null);
            Assert.AreEqual(ExpectedExistingValue, valueFromDatabase);
        }

        [Test]
        public void FindValue_KeyAndNullInDefaultValueNotExistsInDatabase_DefaultFormattedValue()
        {
            string valueFromDatabase = ResourceService.FindValue(ExpectedNotExistingKey, null);
            Assert.AreEqual(ExpectedNotExistingVlaue, valueFromDatabase);
        }

        [Test]
        public void FindValue_KeyDefaultValueExists_ReturnValueFromDatabase()
        {
            string valueFromDatabase = ResourceService.FindValue(ExpectedExistingKey, "some wrong default value");
            Assert.AreEqual(ExpectedExistingValue, valueFromDatabase);
        }

        [Test]
        public void FindValue_KeyDefaultValueNotExistInDatabase_ReturnDefaultNotCreate()
        {
            var defaultValue = "Test value";
            var newKeyWithoutValue = "new-key-without-value";
            var returnValueWithoutDefault = string.Format("*DEFAULT {0}*", newKeyWithoutValue);            
            string value = ResourceService.FindValue(newKeyWithoutValue, defaultValue, false);
            Assert.AreEqual(defaultValue, value);
            Assert.AreEqual(returnValueWithoutDefault, ResourceService.FindValue(newKeyWithoutValue), "Value should not be created in database");
        }

        [Test]
        public void FindValue_KeyDefaultValueNotExistInDatabaseCreateNew_ReturnDefaultAndCreateInDatabase()
        {
            var defaultValue = "Test value";
            var newKeyWithoutValue = "new-key-without-value-last";            
            string value = ResourceService.FindValue(newKeyWithoutValue, defaultValue, true);
            Assert.AreEqual(defaultValue, value);
            Assert.AreEqual(defaultValue, ResourceService.FindValue(newKeyWithoutValue), "Value should be created in database");
        }

        [Test]
        public void IsDefaultValue_KeyAndDefaultValue_ReturnsTrue()
        {
            bool isDefault = ResourceService.IsDefaultValue(ExpectedNotExistingVlaue, ExpectedNotExistingKey);
            Assert.IsTrue(isDefault);
        }

        [Test]
        public void IsDefaultValue_KeyAndNotDeafultValue_ReturnsFalse()
        {
            string value = "value";
            bool isDefault = ResourceService.IsDefaultValue(value, "test-key");
            Assert.IsFalse(isDefault);
        }
    }

    public class ResourceByKeyAndLocaleInMemoryCommand : ResourceByKeyAndLocale
    {
        public override Resource ExecuteOne()
        {
            return
                new BusinessServiceFacade<Resource, int>().Find(p => p.Key == Key && p.Locale == Locale).FirstOrDefault();
        }
    }
}
